import { Ref, SetupContext } from "vue";
import BigNumber from "bignumber.js";
import { UseFormat, UseNumber, UseSpinner } from "./types";
import { NumberRangeProps } from "../number-range.props";

type SpinDriection = 'up' | 'down';

export function useSpinner(
    props: NumberRangeProps,
    context: SetupContext,
    displayValue: Ref<string>,
    modelValue: Ref<string | number>,
    useFormatComposition: UseFormat,
    useNumberComposition: UseNumber,
    valueChangedCallback: (numberValue: number | string) => void
): UseSpinner {
    const { format } = useFormatComposition;
    const { getRealValue } = useNumberComposition;

    function canUpward() {
        const value = new BigNumber(modelValue.value || 0);
        if (props.max && !new BigNumber(props.max).isNaN() && value.gte(new BigNumber(props.max))) {
            return false;
        }
        return true;
    }

    function canDownward() {
        const value = new BigNumber(modelValue.value || 0);
        if (props.min && !new BigNumber(props.min).isNaN() && value.lte(new BigNumber(props.min))) {
            return false;
        }
        return true;
    }

    function spin(direction: SpinDriection) {
        if (props.readonly || props.disabled || !props.editable) {
            return;
        }
        const canSpin = direction === 'up' ? canUpward : canDownward;
        const spinMethodName = direction === 'up' ? 'plus' : 'minus';
        if (canSpin()) {
            const originalNumberObject = new BigNumber(modelValue.value || 0);
            const newNumberObject = originalNumberObject[spinMethodName](Number(props.step));
            const value = newNumberObject.toFixed();
            displayValue.value = format(value);
            modelValue.value = getRealValue(newNumberObject);
            valueChangedCallback(modelValue.value);
        }
    }

    function upward() {
        spin('up');
    }

    function downward() {
        spin('down');
    }

    /**
     * 点击微增按钮时或键盘触发 ArrowUp 时执行的方法
     */
    function onClickUpButton($event: MouseEvent) {
        upward();
        $event.stopPropagation();
    }

    /**
     * 点击微减按钮时或键盘触发 ArrowDown 时执行的方法
     */
    function onClickDownButton($event: MouseEvent) {
        downward();
        $event.stopPropagation();
    }

    return { canDownward, canUpward, downward, onClickDownButton, onClickUpButton, upward };
}
